package com.wiscamp.ninechapters.tags.application.services;

import com.wiscamp.ninechapters.common.core.CollectionHelper;
import com.wiscamp.ninechapters.tags.application.assemblers.TagAssembler;
import com.wiscamp.ninechapters.tags.application.dto.command.CreateTagCommand;
import com.wiscamp.ninechapters.tags.application.dto.command.UpdateTagCommand;
import com.wiscamp.ninechapters.tags.application.dto.vo.TagGroupVO;
import com.wiscamp.ninechapters.tags.application.dto.vo.TagNameVO;
import com.wiscamp.ninechapters.tags.application.dto.vo.TagVO;
import com.wiscamp.ninechapters.tags.domain.repositories.TagRepository;
import com.wiscamp.ninechapters.tags.domain.services.TagService;
import cube.common.core.CollectionUtils;
import cube.ddd.application.BaseAppService;
import cube.ddd.application.command.DeleteCommand;
import cube.ddd.application.command.DisableCommand;
import cube.ddd.application.command.EnableCommand;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.utils.AppServiceUtils;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.springframework.stereotype.Service;

import java.util.Collection;

@Service
public class TagAppService extends BaseAppService {

    private final TagRepository tagRepository;

    private final TagService tagService;

    public TagAppService(TagRepository tagRepository, TagService tagService) {
        this.tagRepository = tagRepository;
        this.tagService = tagService;
    }


    // region tag
    @HandleServiceException
    public TagVO getTag(long tagId) {
        return AppServiceUtils.getById(tagId, tagService::getTag, TagAssembler.Instance::toTagVO);
    }

    @HandleServiceException
    public TagVO getTagByCode(@NotBlank String tagCode, long appId) {
        return AppServiceUtils.getByTextAndId(tagCode, appId, tagRepository::getTagByCode, TagAssembler.Instance::toTagVO);
    }

    @HandleServiceException
    public TagVO getTagByName(@NotBlank String groupName, @NotBlank String tagName, @Min(0) long appId) {
        var tag = tagRepository.getTagByName(groupName, tagName, appId);
        return TagAssembler.Instance.toTagVO(tag);
    }

    @HandleServiceException
    public Collection<TagVO> getTagsByGroupName(@NotBlank String groupName, long appId) {
        return AppServiceUtils.getListByTextAndId(groupName, appId, tagRepository::getTagsByGroupName,
                TagAssembler.Instance::toTagVO);
    }

    @HandleServiceException
    public Collection<TagNameVO> getTagNamesByIds(@NotEmpty Collection<Long> tagIds) {
        var tagNames = tagRepository.getTagsByIds(tagIds);
        return CollectionHelper.convertToArrayList(tagNames, TagAssembler.Instance::toSimpleTagVO);
    }

    @HandleServiceException
    public TagVO createTag(@NotNull CreateTagCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.createOrUpdateBy(command, command.getOperatorId(), tagService::createTag,
                TagAssembler.Instance::toTagVO,
                TagAssembler.Instance::toTag);
    }

    @HandleServiceException
    public TagVO updateTag(@NotNull UpdateTagCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.createOrUpdateBy(command, command.getOperatorId(), tagService::updateTag,
                TagAssembler.Instance::toTagVO,
                TagAssembler.Instance::toTag);
    }

    @HandleServiceException
    public boolean deleteTag(@NotNull DeleteCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.delete(command.getId(), command.getOperatorId(), tagService::deleteTag);
    }

    @HandleServiceException
    public boolean enableTag(@NotNull EnableCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.enable(command.getId(), command.getOperatorId(), tagService::enableTag);
    }

    @HandleServiceException
    public boolean disableTag(@NotNull DisableCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.disable(command.getId(), command.getOperatorId(), tagService::disableTag);
    }

    // endregion
    @HandleServiceException
    public Collection<TagGroupVO> getAvailableTagGroups() {
        var groups = tagRepository.getAvailableTagGroups();
        return CollectionUtils.toArrayList(groups, TagAssembler.Instance::toTagGroupVO);
    }
}
